package happy.town.threeBook;


import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Scanner;

/**
 * @BelongsProject: threeBook
 * @BelongsPackage: a.happy.town.threeBook
 * @Author: ByHappy  (Email:1300985301@qq.com)
 * @CreateTime: 2023-07-30 16:20
 * @Description: 用户注册功能
 * @Version: 1.0
 **/
class UserRegister {
    /**
     * 注册主体方法
     *
     * @param
     * @author ByHappy
     * @date 12:25 2023/8/20
     **/
    public static void register() {
        // 1、键盘录入用户名
        Scanner sc = new Scanner(System.in);
        String username;
        while (true) {
            System.out.println("请输入长度规范为3~15之间的字母+数字用户名");
            username = sc.next();
            // 1）先验证格式是否正确，再验证是否唯一（因为以后所有的数据，都是存在数据库中的）

            boolean flag1 = checkUsername(username);
            if (!flag1) {
                System.out.println("用户名格式输入不符合规范，请重新输入...");
                //System.out.println("格式正确，OK");
                continue;
            }


            // 2) 验证用户名是否唯一
            // username到集合中判断是否存在
            boolean flag2 = usernameR(username, null, true);
            if (flag2) {
                // 用户名已存在，那么当前用户名无法注册，需要重新输入
                System.out.println("用户名:" + username + "已经存在，请您重新输入...");
            } else {
                // 不存在，表示当前用户名可用，可以继续录入下面的其他数据
                System.out.println("用户名:" + username + "可以用，OK! 请进行下一步操作");
                break;
            }
        }

        // 2、键盘录入密码
        // 密码输入两次，两次一致才可以进行注册
        String password;
        while (true) {
            System.out.println("请输入您的新密码：");
            password = sc.next();
            System.out.println("请再次确认新密码");
            String againPassword = sc.next();
            if (password.equals(againPassword)) {
                System.out.println("两次密码输入一致，请进行下一步操作");
                break;
            } else {
                System.out.println("两次密码输入不一致，请重新输入...");
                continue;
            }
        }

        // 3、键盘录入身份证号码
        String personID;
        while (true) {
            System.out.println("请输入身份证号码");
            personID = sc.next();
            boolean flag = checkPersonID(personID);
            if (flag) {
                System.out.println("身份证号码格式，OK! 请进行下一步操作");
                break;
            } else {
                System.out.println("身份证号码格式有误，请重新输入");
                continue;
            }
        }

        // 4、 键盘录入手机号码
        String phoneNumber;
        while (true) {
            System.out.println("请输入手机号码");
            phoneNumber = sc.next();
            boolean flag = checkPhoneNumber(phoneNumber);
            if (flag) {
                System.out.println("手机号码格式 OK!");
                break;
            } else {
                System.out.println("手机号码格式错误，请重新输入...");
                continue;
            }
        }

        // 在此处改动————————————————————————————————————集合——IO——SQL
        // 用户名，密码，身份证号码，手机号码入到用户对象中
        UserDTO userDTO = new UserDTO(0, username, password, personID, phoneNumber);
        // 调用添加书籍方法
        int user = insertUser(userDTO);
        if (user != 0) {
            System.out.println("注册成功");
        } else {
            System.out.println("注册失败");
        }

    }

    /**
     * 添加书籍sql方法
     *
     * @param userDTO
     * @return int
     * @author ByHappy
     * @date 14:48 2023/8/20
     **/
    private static int insertUser(UserDTO userDTO) {
        Connection conn = null;
        Statement stat = null;
        int result = 0;
        try {
            conn = JDBCUtils.getConnection();

            //3.获取执行者对象
            stat = conn.createStatement();

            //4.执行sql语句，并且接收返回的结果集
            String sql = "INSERT INTO t_user VALUES ('" + userDTO.getUid() + "','" + userDTO.getUsername() + "','" + userDTO.getPassword() + "','" + userDTO.getPersonID() + "','" + userDTO.getPhoneNumber() + "')";
            result = stat.executeUpdate(sql);

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //6.释放资源
            JDBCUtils.close(conn, stat);
        }
        //将结果返回
        return result;
    }

    /**
     * 手机号验证
     *
     * @param phoneNumber
     * @return boolean
     * @author ByHappy
     * @date 21:12 2023/7/30
     **/
    public static boolean checkPhoneNumber(String phoneNumber) {
        // 1)长度为11位
        if (phoneNumber.length() != 11) {
            return false;
        }

        // 2)不能以0为开头
        if (phoneNumber.startsWith("0")) {
            return false;
        }

        // 3)必须都是数字
        for (int i = 0; i < phoneNumber.length(); i++) {
            char c = phoneNumber.charAt(i);
            if (!(c >= '0' && c <= '9')) {
                return false;
            }
        }

        // 当循环结束之后，表示每一个字符都在0~9之间
        return true;
    }

    /**
     * 身份证号码验证
     *
     * @param personID
     * @return boolean
     * @author ByHappy
     * @date 20:40 2023/7/30
     **/
    public static boolean checkPersonID(String personID) {
        // 验证要求：
        // 1)长度为18位
        if (personID.length() != 18) {
            return false;
        }
        // 2)不能以0为开头
        if (personID.startsWith("0")) {
            // 如果是以0开关，那么返回false
            return false;
        }

        // 3)前17位，必须都是数字
        for (int i = 0; i < personID.length() - 1; i++) {
            char c = personID.charAt(i);
            // 如果有一个字符不在0~9之间，那么直接返回false
            if (!(c >= '0' && c <= '9')) {
                return false;
            }
        }

        // 4)最为一位可以是数字，也可以是大写X或小写x
        char endelement = personID.charAt(personID.length() - 1);
        if ((endelement >= '0' && endelement <= '9') || (endelement == 'x') || (endelement == 'X')) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 判断username是否唯一
     *
     * @param username
     * @param estimate
     * @return boolean
     * @author ByHappy
     * @date 15:12 2023/8/20
     **/
    public static boolean usernameR(String username, String password, boolean estimate) {
        Connection conn = null;
        PreparedStatement pstm = null;
        Statement stat = null;
        ResultSet rs = null;
        UserDTO userDTO = null;
        //最终值
        boolean flag = false;
        //为true则是判断账号是否被注册，为false则是判断当前账号登录是否成功
        boolean pd = estimate;
        try {
            conn = JDBCUtils.getConnection();

            // 3.获取执行者对象
            stat = conn.createStatement();

            // 4.执行sql语句，并且接收返回的结果集
            String sql = "select * from t_user WHERE username=?";

            pstm = conn.prepareStatement(sql);
            // 3.设置参数
            pstm.setString(1, username);//设置第一个?参数
            //pstm.setString(2, password);//设置第二个?参数
            // System.out.println(sql);
            // 4.执行sql语句，获取结果集
            rs = pstm.executeQuery();
            //5.获取结果集
            if (rs.next()) {
                //6.封装
                userDTO = new UserDTO();
                userDTO.setUsername(rs.getString("username"));
                userDTO.setPassword(rs.getString("password"));

            }


            if (pd) {
                //为true则是判断账号是否被注册，为false则是判断当前账号登录是否成功
                if ((userDTO.getUsername().equals(username))) {
                    flag = true;
                }
            } else {
                if ((userDTO.getUsername().equals(username) && (userDTO.getPassword().equals(password)))) {
                    flag = true;
                }
            }


        } catch (Exception e) {

        } finally {
            //6.释放资源
            JDBCUtils.close(conn, stat);
        }
        //将结果返回
        return flag;

    }

    /**
     * 判断username长度 和数字+字母规范
     *
     * @param username
     * @return boolean
     * @author ByHappy
     * @date 17:48 2023/7/30
     **/
    private static boolean checkUsername(String username) {
        // 1.1）用户名长度必须在3~15位之间
        int len = username.length();
        if (len < 3 || len > 15) {
            return false;
        }


        // 代码执行到这里，表示上面条件已满足


        // 1.2）只能是字母加数字的组合，但是不能是纯数字
        // 循环得到username里面的每一个字符，如果有一个字符不是字母或者数字，那么就返回false
        for (int i = 0; i < username.length(); i++) {
            // i 索引
            char element = username.charAt(i);
            if (!((element >= 'a' && element <= 'z') || (element >= 'A' && element <= 'Z') || (element >= '0' && element <= '9'))) {
                return false;
            }
        }

        // 代码执行到这里，表示上面条件都已满足（长度满足，字母+数字也满足）

        // 继续判断不能是纯数字的条件，统计username中，有多少字母就可以了
        int count = 0;
        for (int i = 0; i < username.length(); i++) {
            char element2 = username.charAt(i);
            if ((element2 >= 'a' && element2 <= 'z') || (element2 >= 'A' && element2 <= 'Z')) {
                count++;
                break; // break可以提高一些效率，其实不用计数很多次
            }
        }


        return count > 0;
    }
}
